package com.duan.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.duan.utils.DateUtils;
import com.duan.utils.IpUtils;
import com.duan.utils.LocalIP;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;

/**
 * @author db
 * @version 1.0
 * @description LoggingAspect
 * @since 2024/1/9
 */
@Slf4j
@Aspect
@Component
public class LoggingAspect {

    /**
     * com.kingsware.aiam.manage.controller 包中公共方法的切入点
     */
//    @Pointcut("execution(public * com.kingsware.aiam.manage.controller.*.*(..))")
    @Pointcut("execution(public * com.duan.controller.*.*(..))")
    public void loggingPointcut(){
        // 暂不用处理
    }

    @Around("loggingPointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        // 获取类名
        String className = pjp.getTarget().getClass().getTypeName();
        // 获取方法名
        String methodName = pjp.getSignature().getName();
        // 获取参数名
        String[] parameterNames = ((MethodSignature) pjp.getSignature()).getParameterNames();

        Object result = null;
        // 获取参数值
        Object[] args = pjp.getArgs();

        // 获取请求
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 获取请求的url
//        String url = request.getRequestURL().toString();
        String url = IpUtils.getIpAddr(request);

//        String requestIP = IpUtils.getIpAddr(request);



        // 请求参数，以参数名和值为键值对
        Map<String, Object> paramMap = new HashMap<>();
        IntStream.range(0, parameterNames.length).forEach(i->paramMap.put(parameterNames[i], args[i]));

        // header参数
        Enumeration<String> headerNames = request.getHeaderNames();
        Map<String, Object> headerMap = new HashMap<>();
        while (headerNames.hasMoreElements()){
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            headerMap.put(headerName, headerValue);
        }

        // 打印请求参数,记录起始时间
        long start = System.currentTimeMillis();

        try {
            result = pjp.proceed();
            System.out.println(result.toString());
//        } catch (ManageException e) {
//            JSONObject json = new JSONObject();
//            json.put("code",e.getCode());
//            json.put("logType","exception");
//            json.put("errMsg",e.getMsg());
//            json.put("exception",e.getMessage());
//            log.error(json.toJSONString());
//            throw e;
        } catch (Exception e) {
            JSONObject json = new JSONObject();
            json.put("code","500");
            json.put("logType","exception");
            json.put("errMsg","异常发生");
            json.put("exception",e.getMessage());
            log.error(json.toJSONString());
            throw e;
        }

        // 获取执行完的时间 打印返回报文
        JSONObject json = new JSONObject();
        json.put("logType","ACCESS");
        json.put("hostName","znshxt");
        json.put("hostIp", LocalIP.getIpAddress());
        json.put("requestIp",url);
        json.put("requestTime", DateFormatUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss.SSS"));
        json.put("requestParams", JSON.toJSON(paramMap));
        json.put("responseTime", DateFormatUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss.SSS"));
        json.put("responseParams",JSON.toJSON(result));
        json.put("consumeTime",System.currentTimeMillis() - start);
//        json.put("httpMethod",request.getMethod());
//        json.put("className",className);
//        json.put("classMethod",methodName);
        log.info(json.toJSONString());
        return result;
    }
}
